/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.coreGenerator.base.dualaccgen;

import com.inspur.edp.caf.generator.BaseGenerator;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.caf.generator.property.ClassPropertyGenerator;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.gencommon.MediateType;
import com.inspur.edp.cef.generator.common.MediatePropertyInfo;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.EnrichedAssoUdtAcsGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.EnrichedAssoUdtReadonlyAcsGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.method.AccGetResInfoGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.method.AccessorCreateNewGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.method.AccessorDataGetValueGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.method.AccessorDataSetValueGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.method.base.AccessorInitializeGen;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.method.base.AcsCopyGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.property.DynamicPropAcsPropertyGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.property.InnerDataGeneratpr;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.property.NestedAccessorPropertyGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.dualaccgen.method.DualAccCreateNewGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.dualaccgen.method.DualAccCtorGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.dualaccgen.method.DualAccIsReadonlyGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.dualaccgen.method.DualAccNormalPropGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.BaseDataGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.EntityGeneratorContext;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.field.ChildFieldGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.property.BaseTypePropGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.property.DataTypePropGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.property.DynamicPropSetPropertyGenerator;
import com.inspur.edp.cef.generator.overall.GeneratorUtil;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.core.dom.Modifier;

public abstract class BaseDualAcsGenerator extends BaseDataGenerator {

  protected static final String isReadonlyFieldName = "accReadonly";

  public BaseDualAcsGenerator(EntityGeneratorContext parContext, IGspCommonDataType node,
      MediateType targetInterfaceType) {
    super(parContext, node, targetInterfaceType);
    parContext.getProjContext().getAccessorMediateTypes()
        .put(node.getCode(), new MediateType(getNameSpace(), getName()));
    parContext.getProjContext().getReadonlyAccessorMediateTypes()
        .put(node.getCode(), new MediateType(getNameSpace(), getName()));
  }

  protected String getNameSpace() {
    return "";
  }

  @Override
  protected String getName() {
    return GeneratorUtil.remove(TargetInterfaceType.getClassName()).concat("Acc");
  }

  @Override
  protected ArrayList<Modifier.ModifierKeyword> getAccessModifier() {
    ArrayList<Modifier.ModifierKeyword> list = new ArrayList<>();
    list.add(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
    return list;
  }

  @Override
  protected ArrayList<ClassMethodGenerator> createConstructorGenerators() {
    ArrayList<ClassMethodGenerator> list = super.createConstructorGenerators();
    if (list == null) {
      list = new ArrayList<>();
    }
    FieldGenerators.add(new ChildFieldGenerator(isReadonlyFieldName, new TypeInfo(boolean.class)));
    list.add(new DualAccCtorGenerator(getName(), TargetInterfaceType, isReadonlyFieldName));
    return list;
  }

  @Override
  protected DataTypePropGenerator getDataTypePropGenerator(MediatePropertyInfo propertyInfo,
      String fieldName) {
    return new NestedAccessorPropertyGenerator(propertyInfo);
  }

  @Override
  protected List<BaseTypePropGenerator> getBaseTypePropGenerators(
      MediatePropertyInfo propertyInfo) {
    List<BaseTypePropGenerator> baseTypePropGenerators = new ArrayList<>();
    baseTypePropGenerators
        .add(new DualAccNormalPropGenerator(ParentContext, NodeCode, propertyInfo));
    if (Character.isLowerCase(propertyInfo.getPropertyName().charAt(0)) && !propertyInfo
        .getExtendInfos().containsKey("AssoUdtAtrribute")) {
      baseTypePropGenerators
          .add(new DualAccNormalPropGenerator(ParentContext, NodeCode, propertyInfo, true));
    }
    return baseTypePropGenerators;
  }

  @Override
  protected void addExtendPropertyGenerator(ArrayList<ClassPropertyGenerator> proGenerators) {
    InnerDataGeneratpr innerDataGen = new InnerDataGeneratpr(TargetInterfaceType);
    proGenerators.add(innerDataGen);
  }

  @Override
  protected ArrayList<ClassMethodGenerator> createMethodGenerators() {
    ArrayList<ClassMethodGenerator> methods = super.createMethodGenerators();
    if (methods == null) {
      methods = new ArrayList<>();
    }

    ClassMethodGenerator getValueGen = getAccessorDataGetValueGenerator();
    ClassMethodGenerator setValueGen = getAccessorDataSetValueGenerator();
    methods.add(getValueGen);
    methods.add(setValueGen);
    DualAccIsReadonlyGenerator readOnlyGen = new DualAccIsReadonlyGenerator(isReadonlyFieldName);
    methods.add(readOnlyGen);
    methods.add(getInitilizeGenerator());
    methods.add(getRestGenerator());
    methods.add(new DualAccCreateNewGenerator(getName()));
    addAcsExtendMethod(methods);
    ClassMethodGenerator resGen = get_GetResInfo_Generator();
    if (resGen != null) {
      methods.add(resGen);
    }
    return methods;
  }

  protected ClassMethodGenerator getAccessorDataGetValueGenerator() {
    return new AccessorDataGetValueGenerator(ParentContext, NodeCode);
  }

  protected ClassMethodGenerator getAccessorDataSetValueGenerator() {
    return new AccessorDataSetValueGenerator(ParentContext, NodeCode);
  }

  public abstract AccessorInitializeGen getInitilizeGenerator();

  public AcsCopyGenerator getRestGenerator() {
    return new AcsCopyGenerator(getName(), NodeCode, PropertyInfos, ParentContext);
  }

  protected void addAcsExtendMethod(ArrayList<ClassMethodGenerator> methodGens) {
  }

  @Override
  protected ArrayList<TypeInfo> addParentInterfaces() {
    ArrayList<TypeInfo> list = new ArrayList<>();
    TypeInfo info = new TypeInfo(TargetInterfaceType.getFullName());
    info.setUseFullName(true);
    list.add(info);
    return list;
  }

  @Override
  protected void addEnrichedAssoUdtGenerator(ArrayList<BaseGenerator> list,
      MediatePropertyInfo propInfo) {
    list.add(new EnrichedAssoUdtAcsGenerator(ParentContext, propInfo, getName()));
    list.add(new EnrichedAssoUdtReadonlyAcsGenerator(ParentContext, propInfo, getName()));
  }

  @Override
  protected DynamicPropSetPropertyGenerator getDynamicPropSetPropertyGenerator(
      MediatePropertyInfo propertyInfo) {
    return new DynamicPropAcsPropertyGenerator(propertyInfo);
  }

  protected ClassMethodGenerator get_GetResInfo_Generator() {
    if (ParentContext.getProjContext().getEntityMediateTypes().get(NodeCode) != null) {
      return new AccGetResInfoGenerator(ParentContext, NodeCode);
    }
    return null;
  }
}
